﻿using Aspfm.Main;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Aspfm.Main
{
    //delegate void WriteLog(LogType prev, string msg, string objId, AspfmModel dynobj);

    [Serializable()]
    public enum LogType
    {
        CommonLog,
        SQLLog,
        ErrLog,
        WebApp,
        AspfmServers
    }
    [Serializable()]
    public class WriteLogModel
    {
        public LogType prev= LogType.WebApp;
        public string msg=string.Empty;
        public string objId=string.Empty;
        public AspfmModel dynobj = null;
        public UserIdentity user = null;
        public string functionname = "";
    }
    public class Loger
    {
        //static List<object> LogWritingLock = new List<object>();
        //static int MaxWritingCount = 10;
        static object obj = new object();
        static object errobj = new object();

        internal static void Init()
        {
            //if (LogWritingLock.Count <= 0)
            //{
            //    for (int i = 0; i < MaxWritingCount; i++)
            //    {
            //        object obj = new object();
            //        LogWritingLock.Add(obj);
            //    }
            //}
        }
        static void WriteLogFileThread(object obj)
        {
            if (obj != null && obj is WriteLogModel)
            {
                WriteLogModel templog = (WriteLogModel)obj;
                WriteLogFile(templog.prev, templog.functionname, templog.msg, templog.objId, templog.dynobj, templog.user);
            }
        }
        static void WriteLogFile(LogType prev,string functionname, string msg, string objId, AspfmModel dynobj, UserIdentity user)
        {
            string logfile = GetLogFileName(prev);
            StringBuilder sbstr = new StringBuilder(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            sbstr.AppendLine("   [" + user.LoginGuid + "]   [" + user._uname + "]   [" + user._uno + "]   [" + objId + "]");
            sbstr.AppendLine(msg);
            if (dynobj != null && dynobj.Values.Count > 0)
            {
                sbstr.Append("{Params:");
                foreach (System.Collections.DictionaryEntry kv in dynobj.Values)
                {
                    sbstr.Append("[" + kv.Key + ":" + kv.Value + "]");
                }
                sbstr.Append("}   ");
                sbstr.AppendLine();
            }
            sbstr.AppendLine("[" + functionname + "]");
            //WriteLog1(logfile, sbstr);
            if (prev == LogType.ErrLog)
            {
                lock (errobj)
                {
                    try
                    {
                        System.IO.File.AppendAllText(logfile, "【" + sbstr.ToString() + "】\r\n", Encoding.UTF8);
                    }
                    catch { }
                }
            }
            else
            {
                lock (obj)
                {
                    try
                    {
                        System.IO.File.AppendAllText(logfile, "【" + sbstr.ToString() + "】\r\n", Encoding.UTF8);
                    }
                    catch { }
                }
            }
        }

        /*  测试同步写10个日志文件与同步写一个文件。10W日志性能193 199。忽略不计
        private static void WriteLog1(string logfile, StringBuilder sbstr)
        {
            string name=Path.GetFileNameWithoutExtension(logfile).Split('-')[2];
            int WritingIndex = int.Parse(name);
            //object obj=LogWritingLock[WritingIndex];
            if (WritingIndex == 0)
            {
                lock (obj)
                {
                    //try
                    //{

                        System.IO.File.AppendAllText(logfile, sbstr.ToString(), Encoding.UTF8);
                    //}
                    //catch { }
                }
            }
            else if (WritingIndex == 1)
            {
                lock (obj1)
                {
                    System.IO.File.AppendAllText(logfile, sbstr.ToString(), Encoding.UTF8);
                }
            }
            else if (WritingIndex == 2)
            {
                lock (obj2)
                {
                    System.IO.File.AppendAllText(logfile, sbstr.ToString(), Encoding.UTF8);
                }
            }
            else if (WritingIndex == 3)
            {
                lock (obj3)
                {
                    System.IO.File.AppendAllText(logfile, sbstr.ToString(), Encoding.UTF8);
                }
            }
            else if (WritingIndex ==4)
            {
                lock (obj4)
                {
                    System.IO.File.AppendAllText(logfile, sbstr.ToString(), Encoding.UTF8);
                }
            }
            else if (WritingIndex == 5)
            {
                lock (obj5)
                {
                    System.IO.File.AppendAllText(logfile, sbstr.ToString(), Encoding.UTF8);
                }
            }
            else if (WritingIndex == 6)
            {
                lock (obj6)
                {
                    System.IO.File.AppendAllText(logfile, sbstr.ToString(), Encoding.UTF8);
                }
            }
            else if (WritingIndex == 7)
            {
                lock (obj7)
                {
                    System.IO.File.AppendAllText(logfile, sbstr.ToString(), Encoding.UTF8);
                }
            }
            else if (WritingIndex == 8)
            {
                lock (obj8)
                {
                    System.IO.File.AppendAllText(logfile, sbstr.ToString(), Encoding.UTF8);
                }
            }
            else if (WritingIndex == 9)
            {
                lock (obj9)
                {
                    System.IO.File.AppendAllText(logfile, sbstr.ToString(), Encoding.UTF8);
                }
            }
        }
        private void button2_Click(object sender, EventArgs e)
        {
            //DbFactory.WriteLog(LogType.WebApp, "sdf","",true);

            Aspfm.Dal.DbFactory.GetCurrentUserid += DbFactory_GetCurrentUserid;
            //for (int j = 0; j < 100000; j++)
            //{
            //    DbFactory.WriteLog(LogType.WebApp, "123", j.ToString());
            //}
            int theCount = 2;

            for (int i = 0; i < theCount; i++)
            {
                new Thread(aa, 1024).Start(i);
            }
            MessageBox.Show("sdfsdf");
        }
        public void aa(object o)
        {
            int theI = (int)o;
            string file = "d:\\a" + (theI % 20).ToString() + ".txt";
            DbFactory.WriteLog(LogType.WebApp, theI.ToString() + "开始!");
            for (int j = 0; j < 100000; j++)
            {
                DbFactory.WriteLog(LogType.WebApp, theI.ToString(), j.ToString());
            }
            DbFactory.WriteLog(LogType.WebApp, theI.ToString() + "结束!");
        }
         * */

        private static string GetLogFileName(LogType prev)
        {
            DateTime dt = DateTime.Now;
            //int ThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;  
            string ThreadId = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
            string logpath = Directory.GetParent(BaseAshx.CurrentPath(true).Trim('\\').Trim('/')).FullName;
            logpath = logpath + "\\Aspfm.syslog" + "\\" + dt.Year
                + "\\" + dt.Month + "\\" + dt.Day + "\\" + dt.Hour;
            if (Directory.Exists(logpath) == false)//如果不存在就创建file文件夹
            {
                Directory.CreateDirectory(logpath);
            }
            //Random ran = new Random();
            //int RandKey = ran.Next(0, MaxWritingCount);
            return logpath + "\\" + dt.Minute + "-" + ThreadId + "-" + prev.ToString() + ".log";//后两位用来表达写入锁定
        }

        public static void WriteLog(string Msg, string objid = "", bool asynchronous = true)
        {
            WriteLog(LogType.WebApp, Msg, objid, asynchronous);
        }
        public static void WriteLog(Exception ex)
        {
            WriteLog(LogType.ErrLog, ex.Message + ex.StackTrace, "", false);
        }
        /// <summary>
        /// 写日志
        /// </summary>
        public static void WriteLog(LogType prev, string msg, string objId = "", bool asynchronous = true)
        {
            if (!string.IsNullOrEmpty(msg))
            {
                AspfmModel dynobj = null;
                try
                {
                    if (System.Web.HttpContext.Current != null && System.Web.HttpContext.Current.Request != null)
                    {
                        msg = "[" + msg + "]" + System.Environment.NewLine + "[" + ConfigTool.getIpAddress() + "]   [" +
                            System.Web.HttpContext.Current.Request.RawUrl + "]";
                        if (System.Web.HttpContext.Current.Request.UrlReferrer != null)
                        {
                            msg += "   [" + System.Web.HttpContext.Current.Request.UrlReferrer.ToString() + "]";
                        }
                        if (PageTool.GetAspfmConfig("日志设置", "界面参数") == "1")
                        {
                            dynobj = BaseAshx.GetRequestDynObj(System.Web.HttpContext.Current);
                        }
                    }
                }
                catch { }
                Loger.Init();
                string functionname = GetLogerFullFunction();
                if (asynchronous)
                {
                    //WriteLog handler = new WriteLog(WriteLogFile);
                    //异步操作接口(注意BeginInvoke方法的不同！)
                    //IAsyncResult result = handler.BeginInvoke(1, 2, new AsyncCallback(回调函数), "AsycState:OK");
                    //handler.BeginInvoke(prev, msg, objId, null,null,null);
                    WriteLogModel tempwritelog = new WriteLogModel();
                    tempwritelog.prev = prev;
                    tempwritelog.msg = msg;
                    tempwritelog.objId = objId;
                    tempwritelog.dynobj = dynobj;
                    tempwritelog.functionname = functionname;
                    tempwritelog.user = PageTool.GetCurrentUser();
                    System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(WriteLogFileThread), tempwritelog);
                }
                else
                {
                    WriteLogFile(prev, functionname, msg, objId, dynobj, PageTool.GetCurrentUser());
                }
            }
        }

        private static string GetLogerFullFunction()
        {
            string functionname = "";
            for (int logerindex = 2; ; logerindex++)
            {
                functionname = GetFunctionInfo(logerindex);
                if (functionname.StartsWith("Aspfm.Dal.dll") || functionname.EndsWith("WriteLog"))
                {
                    continue;
                }
                break;
            }
            return functionname;
        }

        public static string GetFunctionInfo(int index=1)
        {
            StackTrace trace = new StackTrace();
            MethodBase methodName = trace.GetFrame(index).GetMethod();
            return methodName.ReflectedType.Module.Name+"，"+methodName.ReflectedType.FullName+"，"+ methodName.Name;
        }
    }
}
